#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <limits.h>
#include <dirent.h>
#include <sys/time.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/socket.h>

#include "data_type.h"
#include "alloc.h"
#include "memfunc.h"
#include "basefunc.h"
#include "struct_deal.h"
#include "crypto_func.h"
#include "memdb.h"
#include "message.h"
#include "ex_module.h"
#include "sys_func.h"
#include "return_value.h"
#include "tcm_constants.h"
#include "tcm_structures.h"
#include "tcmfunc.h"
#include "tcm_cube_struct.h"
#include "tcm_key_manage.h"
#include "tcm_key_desc.h"
#include "tcm_pik_desc.h"
#include "file_struct.h"

#include "tcmkey_sign.h"

BYTE Buf[DIGEST_SIZE*16];
int tcmkey_sign_init(void * sub_proc,void * para)
{
	int ret;
	// add youself's plugin init func here
	return 0;
}

int tcmkey_sign_start(void * sub_proc,void * para)
{
	int ret;
	void * recv_msg;
	int i;
	int type;
	int subtype;


	while(1)
	{
		usleep(time_val.tv_usec);
		ret=ex_module_recvmsg(sub_proc,&recv_msg);
		if(ret<0)
			continue;
		if(recv_msg==NULL)
			continue;
		type=message_get_type(recv_msg);
		subtype=message_get_subtype(recv_msg);
		if((type==TYPE(GENERAL_RETURN))&&(subtype==SUBTYPE(GENERAL_RETURN,UUID)))
		{
			proc_tcm_sign_message(sub_proc,recv_msg);
		}
	}
	return 0;


};

int proc_tcm_sign_message(void * sub_proc,void * message)
{
    int i;
    int ret;
	void * new_msg;

    BYTE blob[32];
    int blob_size;

    BYTE* bind_blob;
    int bind_blob_size;
    int sign_len;

	MSG_EXPAND * msg_expand;
	RECORD(GENERAL_RETURN,UUID)* uuid_record;
	RECORD(GENERAL_RETURN,BINDATA)* sign_data;
    RECORD(VTCM_IN_KEY,TCM_BIN_KEY) * tcmkey;

	RECORD(FILE_TRANS,FILE_DATA) * file_data;
	BYTE Namebuf[DIGEST_SIZE*4];
	char uuid[DIGEST_SIZE*2+1];




    // get key uuid
	//ret=message_remove_expand(message,TYPE_PAIR(GENERAL_RETURN,UUID),&msg_expand);
	ret=message_get_record(message,&uuid_record,0);
	if(ret<0)
		return ret;
	//uuid_record=msg_expand->expand;

    ret=message_get_expand(message,&msg_expand,0);
    file_data = msg_expand->expand;

  int count = 0;
  while(file_data->filename[count] != '\0'){
    blob[count] = (BYTE)file_data->filename[count];
	count++;
  }
  blob_size = count;
print_cubeaudit("get file_msg %s\n",uuid_record->return_value);
    // get tcmkey file name
     Memset(Namebuf,0,DIGEST_SIZE*3);
	 Strcpy(Namebuf,"tcmkey/");
	Strcat(Namebuf,uuid_record->return_value);
	// digest_to_uuid(uuid_record->return_value,Namebuf+Strlen(Namebuf));
	


    // load tcmkey
    printf("Begin load tcmkey ! blob is : %s\n", (char *)blob);
	tcmkey=Talloc0(sizeof(*tcmkey));
	if(tcmkey==NULL)
		return -ENOMEM;
	ret=TCM_ExLoadTcmKey(tcmkey,Namebuf);
	if(ret!=0)
		return -EINVAL;
	print_cubeaudit("get tcmkey %s succeed!\n",Namebuf);

    UINT32 authHandle;
    UINT32 keyHandle;
    UINT32 keyAuthHandle;

   	ret=TCM_APCreate(TCM_ET_SMK, NULL, "sss", &authHandle);
   	if(ret!=0)
   	{
		printf("TCM_APCreate failed!\n");
		return -EINVAL;	
   	}	
   	ret=TCM_LoadKey(0x40000000,authHandle,tcmkey,&keyHandle);
   	if(ret!=0)
    {
		printf("TCM_LoadKey failed!\n");
		return -EINVAL;	
    }	

    ret=TCM_APCreate(TCM_ET_KEYHANDLE, keyHandle, "sss", &keyAuthHandle);
   	if(ret!=0)
    {
		printf("TCM_APCreate %dfailed!\n",12);
		return -EINVAL;	
   	}	

   	ret=TCM_SM2Sign(keyHandle,keyAuthHandle,Buf,&sign_len,blob,blob_size);
   	if(ret!=0)
    {
		print_cubeerr("TCM_SM2Sign%d failed!\n",ret);
		return -EINVAL;	
   	}	

   	ret=TCM_APTerminate(authHandle);
   	if(ret<0)
   	{
 		  printf("TCM_APTerminate %x failed!\n",authHandle);
		  return -EINVAL;	
   	}	
    ret=TCM_APTerminate(keyAuthHandle);
    if(ret!=0)
    {
		printf("TCM_APTerminate %x failed!\n",keyAuthHandle);
		return -EINVAL;	
	}
    ret=TCM_EvictKey(keyHandle);
    if(ret!=0)
    {
		printf("TCM_EvictKey %x failed!\n",keyHandle);
		return -EINVAL;	
    }	


	

    sign_data=Talloc0(sizeof(*sign_data));
    sign_data->name = dup_str("signdata",0);
    sign_data->size=sign_len;
    sign_data->bindata=Talloc0(sign_data->size);
    Memcpy(sign_data->bindata,Buf,sign_data->size);

    new_msg = message_create(TYPE_PAIR(GENERAL_RETURN,UUID),message);
    if(new_msg == NULL)
       return -EINVAL;

	int flag=message_get_flag(message);
    message_set_flag(message,flag|MSG_FLAG_SIGN);
	
  ret = message_add_record(new_msg,uuid_record);
    if(ret < 0)
	   return ret;
  ret=message_add_expand_data(new_msg,TYPE_PAIR(FILE_TRANS,FILE_DATA),file_data);



  


	if(ret<0)
		return ret;
    ret=message_add_expand_data(message,TYPE_PAIR(GENERAL_RETURN,BINDATA),sign_data);
    if(ret<0)
		return ret;

    ex_module_sendmsg(sub_proc,message);

    return ret;
}
